package com.googlecode.pdfbricks.engine;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.pdfbricks.engine.exception.PDFOperationException;
import com.googlecode.pdfbricks.engine.exception.PageIndexOutOfBoundException;
import com.lowagie.text.pdf.BadPdfFormatException;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;

/**
 * @author Johny Huang
 * 
 */
public class PDFOperator {

	public static Log log = LogFactory.getLog(PDFOperator.class);

	/**
	 * Extract the pages from PDF reader to PDF copy.
	 * 
	 * @param desCopy
	 * @param srcReader
	 * @param startPage
	 * @param endPage
	 * @throws PDFOperationException
	 */
	public void extract(PdfCopy desCopy, PdfReader srcReader, int startPage,
			int endPage) throws PDFOperationException {
		int pageSize = srcReader.getNumberOfPages();
		try {
			comparePageSize(startPage, pageSize);
			comparePageSize(endPage, pageSize);

			if (startPage > 0 && endPage > 0) {
				if (endPage >= startPage) {
					for (int i = startPage; i <= endPage; i++) {
						// Copy pages to desFile
						desCopy.addPage(desCopy.getImportedPage(srcReader, i));
					}
				} else {
					for (int i = startPage; i >= endPage; i--) {
						// Copy pages to desFile
						desCopy.addPage(desCopy.getImportedPage(srcReader, i));
					}
				}
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		} catch (BadPdfFormatException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		} catch (PageIndexOutOfBoundException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		}

	}

	/**
	 * Extract all the pages from PDF reader to PDF copy.
	 * 
	 * @param desCopy
	 * @param srcReader
	 * @throws PDFOperationException
	 */
	public void extractAll(PdfCopy desCopy, PdfReader srcReader)
			throws PDFOperationException {
		int pageSize = srcReader.getNumberOfPages();
		try {
			for (int i = 1; i <= pageSize; i++) {
				// Copy pages to desFile
				desCopy.addPage(desCopy.getImportedPage(srcReader, i));
			}
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		} catch (BadPdfFormatException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		}

	}

	/**
	 * Extract a single page from PDF reader to PDF copy.
	 * 
	 * @param desCopy
	 * @param srcReader
	 * @param pageNumber
	 * @throws PDFOperationException
	 */
	public void extract(PdfCopy desCopy, PdfReader srcReader, int pageNumber)
			throws PDFOperationException {
		int pageSize = srcReader.getNumberOfPages();
		try {
			comparePageSize(pageNumber, pageSize);
			desCopy.addPage(desCopy.getImportedPage(srcReader, pageNumber));
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		} catch (BadPdfFormatException e) {
			log.error(e.getMessage(), e);
			throw new PDFOperationException(e.getMessage(), e);
		} catch (PageIndexOutOfBoundException e) {
			log.error(e.getMessage(),e);
			throw new PDFOperationException(e.getMessage(),e);
		}
	}

	/**
	 * Get the total number of pages with the give PDF file path.
	 * 
	 * @param filePath
	 * @return
	 */
	public static int getPdfTotalNumberOfPages(String filePath) {
		int size = 0;
		PdfReader reader = null;
		try {
			reader = new PdfReader(filePath);
			size = reader.getNumberOfPages();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				reader.close();
			}
		}
		return size;
	}

	private void comparePageSize(int index, int pageSize)
			throws PageIndexOutOfBoundException {
		String msg = null;
		if (index > pageSize) {
			msg = "Page index " + index + " larger than the page size "
					+ pageSize;
		}
		if (index < 1) {
			msg = "Invalid page index " + String.valueOf(index);
		}
		if (msg != null) {
			throw new PageIndexOutOfBoundException(msg);
		}
	}
	
	
}
